package com.element.oauth2.resource;

import com.element.oauth2.resource.config.GlobalBearerTokenResolver;
import com.element.oauth2.resource.config.GlobalOpaqueTokenIntrospect;
import com.element.oauth2.resource.config.PermitAllUrlProperties;
import com.element.oauth2.resource.filter.GlobalSecurityFilter;
import com.element.oauth2.resource.filter.SecurityHandlerInterceptor;
import com.element.oauth2.resource.handler.GlobalAuthenticationEntryPoint;
import com.element.oauth2.token.RedisOAuth2AuthorizationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity
@Import(value = {RedisOAuth2AuthorizationService.class, PermitAllUrlProperties.class,
        GlobalSecurityFilter.class, SecurityHandlerInterceptor.class})
public class GlobalResourceServerConfiguration {

    @Autowired
    private OAuth2AuthorizationService oAuth2AuthorizationService;

    @Autowired
    private PermitAllUrlProperties permitAllUrlProperties;

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        String[] urls = permitAllUrlProperties.getIgnoreUrls().toArray(new String[]{});
        http.authorizeRequests(authorizeRequests -> authorizeRequests
                        .antMatchers(urls)
                        .permitAll()
                        .anyRequest()
                        .authenticated())
                .oauth2ResourceServer(
                        oauth2 -> oauth2.opaqueToken(token -> token.introspector(new GlobalOpaqueTokenIntrospect(oAuth2AuthorizationService)))
                                .authenticationEntryPoint(new GlobalAuthenticationEntryPoint())
                                .bearerTokenResolver(new GlobalBearerTokenResolver(permitAllUrlProperties)))
                .headers()
                .frameOptions()
                .disable()
                .and()
                .formLogin().and()
                .csrf()
                .disable();
        return http.build();
    }
}